#include "TextFileReaderAndWriter.h"

std::unordered_map<std::string, std::shared_mutex> textFileRW::TextFileReaderAndWriter::full_file_name_2_mutex = std::unordered_map<std::string, std::shared_mutex>();

std::shared_mutex textFileRW::TextFileReaderAndWriter::global_mutex;

std::shared_mutex& textFileRW::TextFileReaderAndWriter::getMutexFromFullFileName(const std::string& file_name, const std::string& file_extension)
{
	std::string new_full_file_name = (file_extension == "" ? file_name : (file_name + file_extension));
	std::unique_lock<std::shared_mutex> lock(textFileRW::TextFileReaderAndWriter::global_mutex);
	return textFileRW::TextFileReaderAndWriter::full_file_name_2_mutex[new_full_file_name];
}

std::vector<std::string> textFileRW::TextFileReaderAndWriter::read(const std::string& file_name, const std::string& file_extension, std::ios_base::openmode open_mode)
{
	std::string new_full_file_name = (file_extension == "" ? file_name : (file_name + file_extension));
	std::shared_lock<std::shared_mutex> lock(this->getMutexFromFullFileName(new_full_file_name));
	this->fin.open(new_full_file_name, open_mode);
	if (!this->fin.is_open())
	{
		throw std::runtime_error("Failed to open the file for reading: " + new_full_file_name);
		//catch (const std::runtime_error& e)
		//{
		//	std::cout << std::string("Caught an exception: ") + e.what() + "\n";
		//}
		return std::vector<std::string>();
	}
	std::vector<std::string> ans;
	std::string assist = "";
	while (std::getline(this->fin, assist))
	{
		ans.push_back(assist);
	}
	this->fin.close();
	return ans;
}

std::string textFileRW::TextFileReaderAndWriter::readIntoOneString(const std::string& file_name, const std::string& file_extension, std::ios_base::openmode open_mode)
{
	std::string new_full_file_name = (file_extension == "" ? file_name : (file_name + file_extension));
	std::shared_lock<std::shared_mutex> lock(this->getMutexFromFullFileName(new_full_file_name));
	this->fin.open(new_full_file_name, open_mode);
	if (!this->fin.is_open())
	{
		throw std::runtime_error("Failed to open the file for reading: " + new_full_file_name);
		//catch (const std::runtime_error& e)
		//{
		//	std::cout << std::string("Caught an exception: ") + e.what() + "\n";
		//}
		return std::string();
	}
	std::string content((std::istreambuf_iterator<char>(this->fin)), std::istreambuf_iterator<char>());
	this->fin.close();
	return content;
}

bool textFileRW::TextFileReaderAndWriter::write(const std::string& text, const std::string& file_name, const std::string& file_extension, std::ios_base::openmode open_mode)
{
	std::string new_full_file_name = (file_extension == "" ? file_name : (file_name + file_extension));
	std::unique_lock<std::shared_mutex> lock(this->getMutexFromFullFileName(new_full_file_name));
	this->fout.open(new_full_file_name, open_mode);
	if (!this->fout.is_open())
	{
		throw std::runtime_error("Failed to open the file for writing: " + new_full_file_name);
		//catch (const std::runtime_error& e)
		//{
		//	std::cout << std::string("Caught an exception: ") + e.what() + "\n";
		//}
		return false;
	}
	this->fout << text;
	return true;
}
